import urllib2
import httplib
import socket
import cookielib
import ssl
from crawlerObject import DictCache
import threading
import types
def isclass(obj):
    return isinstance(obj, types.ClassType) or hasattr(obj, "__bases__")

def create_connection(address, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
                      source_address=None,dns_cache=None):
    """Connect to *address* and return the socket object.

    Convenience function.  Connect to *address* (a 2-tuple ``(host,
    port)``) and return the socket object.  Passing the optional
    *timeout* parameter will set the timeout on the socket instance
    before attempting to connect.  If no *timeout* is supplied, the
    global default timeout setting returned by :func:`getdefaulttimeout`
    is used.  If *source_address* is set it must be a tuple of (host, port)
    for the socket to bind as a source address before making the connection.
    An host of '' or port 0 tells the OS to use the default.
    """

    host, port = address
    err = None
    addrinfos=[]
    if(dns_cache):
        addrinfos=dns_cache.get(address)
        if(addrinfos==None):
            addrinfos=socket.getaddrinfo(host,port,0,socket.SOCK_STREAM)
            #print 'adding %s %s' % (str(address),str(addrinfos))
            if(addrinfos):
                dns_cache.add(address,addrinfos)
        #else:
            #print 'get ok %s %s' %(str(address),str(addrinfos))
    else:
        addrinfos=socket.getaddrinfo(host,port,0,socket.SOCK_STREAM)

    for res in addrinfos:
        af, socktype, proto, canonname, sa = res
        sock = None
        try:
            sock = socket.socket(af, socktype, proto)
            if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
                sock.settimeout(timeout)
            if source_address:
                sock.bind(source_address)
            sock.connect(sa)
            return sock

        except socket.error as _:
            err = _
            if sock is not None:
                sock.close()

    if err is not None:
        raise err
    else:
        raise socket.error("getaddrinfo returns an empty list")



def MyResolver(host):
  if host == 'news.bbc.co.uk':
    return '66.102.9.104' # Google IP
  else:
    return host



class DNSCacheHTTPConnection(httplib.HTTPConnection):
    _dnscache=None
    @staticmethod
    def setdnscache(cache):
        DNSCacheHTTPConnection._dnscache=cache
    

    def connect(self):
        self.sock = create_connection((self.host,self.port),self.timeout,dns_cache=DNSCacheHTTPConnection._dnscache)

class DNSCacheHTTPSConnection(httplib.HTTPSConnection):
    _dnscache=None
    @staticmethod
    def setdnscache(cache):
        DNSCacheHTTPSConnection._dnscache=cache
  
    def connect(self):
        sock = create_connection((self.host,self.port),self.timeout,dns_cache=DNSCacheHTTPSConnection._dnscache)
        self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)

class DNSCacheHTTPHandler(urllib2.HTTPHandler):
    def http_open(self,req):
        return self.do_open(DNSCacheHTTPConnection,req)

class DNSCacheHTTPSHandler(urllib2.HTTPSHandler):
    def https_open(self,req):
        return self.do_open(DNSCacheHTTPSConnection,req)

def add_handler(handler):
    for h in urllib2._opener.handlers:
        if(isclass(handler)):
            if(issubclass(handler,h.__class__)):
                urllib2._opener.handlers.remove(h)
        elif(isinstance(handler,h.__class__)):
            urllib2._opener.handlers.remove(h)
   
    if(isclass(handler)):
        handler=handler()
    urllib2._opener.add_handler(handler)

def addDNSCache(cacheSize):
    if(urllib2._opener==None):
        opener=urllib2.build_opener()
        urllib2.install_opener(opener)
    cache=DictCache(size=cacheSize)
    DNSCacheHTTPConnection.setdnscache(cache)
    DNSCacheHTTPSConnection.setdnscache(cache)
     
    add_handler(DNSCacheHTTPHandler)
    add_handler(DNSCacheHTTPSHandler)

if __name__=='__main__':
    socket.setdefaulttimeout(10)

    #DNSCacheHTTPConnection.setdnscache(cache)
    #DNSCacheHTTPSConnection.setdnscache(cache)
    #opener = urllib2.build_opener()#(DNSCacheHTTPHandler,DNSCacheHTTPSHandler)
    #urllib2.install_opener(opener)
    #add_handler(DNSCacheHTTPHandler)
    #add_handler(DNSCacheHTTPSHandler)
    #print(urllib2._opener.handlers)
    #print opener == urllib2._opener
    addDNSCache(10)

    url="http://www.baidu.com"
    url2="https://www.google.com"
    f = urllib2.urlopen(url)
    #f = urllib2.urlopen(url)
    f=urllib2.urlopen(url2) 
    f=urllib2.urlopen(url2) 
    #data = f.read()
    #print len(data)
